package org.fg.logcommon.aop;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.thread.ThreadUtil;
import com.fingard.luna.framework.base.log.LogConstants;
import com.fingard.luna.framework.base.log.LogUtil;
import com.fingard.luna.framework.base.multithread.ThreadAttributeKey;
import com.fingard.luna.framework.base.multithread.ThreadContext;
import com.fingard.luna.framework.base.multithread.ThreadPoolManager;
import com.fingard.luna.framework.boot.core.util.SpringEnvironmentUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.MDC;

import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * 将任务运行的方法转换成异步调用
 */
public class AsyncTaskExecuteAspect implements MethodInterceptor {

    /**
     * 无限扩展的线程池
     * 作用是当请求数量较少时，不必重复创建线程
     */
    private static final ExecutorService LUNA_TASK_ASYNC_EXECUTOR_POOL = ThreadPoolManager.createThreadPool(
            "LUNA_TASK_ASYNC_EXECUTOR_POOL", SpringEnvironmentUtil.AVAILABLE_PROCESSORS + 1, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
            new SynchronousQueue<>(), ThreadUtil.newNamedThreadFactory("LUNA_TASK_ASYNC_EXECUTOR_POOL", false)
    );


    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Logger logger = LogUtil.getLogger(invocation.getMethod().getDeclaringClass());
        ThreadContext.setInheritableAttribute(ThreadAttributeKey.LOGGER, logger);
        Method method = invocation.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        Object[] taskArgs = invocation.getArguments();
        String mehtodName = method.getName();
        String taskId = UUID.randomUUID().toString();

        logger.info("开始执行任务：targetClass = {}, mehtodName = {}, taskArgs = {}", targetClass, mehtodName, taskArgs);

        LUNA_TASK_ASYNC_EXECUTOR_POOL.execute(() -> {
            //耗时计算
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 任务事件信息
//            MDC.put(LogConstants.TASK_DISCRIMINATOR_KEY, LogHelper.generalTaskLogFileName(taskName, taskRunHistoryId));
            try {
                String msg = String.format("任务开始运行，任务调用信息【%s】", targetClass + mehtodName);
                logger.info(msg);
                Object result = invocation.proceed();
                msg = String.format("任务结束运行，任务调用信息【%s】", targetClass + mehtodName);
                logger.info(msg);
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                MDC.remove(LogConstants.TASK_DISCRIMINATOR_KEY);
                stopWatch.stop();
                long totalTimeMillis = stopWatch.getTotalTimeMillis();
                logger.info("任务id为[{}]的任务运行耗时为[{}]ms", taskId, totalTimeMillis);
            }
        });
        return null;
    }

}
